#include "paral_py.h"

// 提供一系列函数，扫描整个文件，分别出不同

// 扫描，不断得到所有token，获取所有的函数，获得串行函数和并行函数
// 的名称和位置
void scan_all_function(struct paral_py_context *ctx)
{
    int tok_id = get_tok(ctx);

    // 做两件事情，找到所有的函数，分清楚函数类型
    // 函数在文件中的范围
    while (tok_id != tok_eof)
    {
        // 处理算子
        if (tok_id == tok_seq_comm_assoca_def_type || tok_id == tok_seq_def_type ||
            tok_id == tok_input_central_paral_type || tok_id == tok_iter_central_paral_type)
        {

            // 对于函数的声明必须缩进为0
            if (ctx->tab_size != 0)
            {
                printf("function declare with no tab\n");
                exit(-1);
            }

            // 下一个语元是函数的名称
            if (get_tok(ctx) == tok_identifier)
            {
                int begin_line = ctx->line_num;
                int end_line = begin_line;
                int tok_in_func;
                std::string function_name = ctx->identifier_str;


                // 不断地获取语元，直到缩进为0，才代表
                while (1)
                {
                    tok_in_func = get_tok(ctx);

                    // printf("line:%d\n", ctx->line_num);

                    // print_token_type(tok_in_func);

                    // printf("\n");

                    if(tok_in_func==tok_tab && ctx->tab_size == 0){
                        end_line = (ctx->line_num) - 1;

                        // 开始位置和结束位置不能是同一行
                        if(end_line == begin_line){
                            continue;
                        }

                        break;
                    }
                    if(tok_in_func==tok_eof){

                        // printf("line:%d\n", ctx->line_num);

                        end_line = ctx->line_num;

                        if(end_line == begin_line){
                            printf("no block of function\n");
                            exit(-1);
                        }

                        break;
                    }
                }

                // assert(end_line != 0);

                // printf("%d,%d\n", ctx->line_num, end_line);

                add_item_to_function_table(ctx, function_name, tok_id, begin_line, end_line);

                // 如果读完文件，直接退出
                if(tok_in_func==tok_eof){
                    return;
                }
            }
            else
            {
                printf("function name is not followed\n");
                exit(-1);
            }
        }


        // 处理对于库的引入，查看import和from
        // 如果出现这两个关键字，就把这两行代码存起来
        if(tok_id == tok_python_remain && (ctx->identifier_str == "import" || ctx->identifier_str == "from")){
            std::string import_code_str = ctx->identifier_str + " ";
            int tok_in_import = 0;
            // 遍历代码剩下的部分，然后存下来，在之后的保留字中，import as这两个保留字前后要留空格
            while(1){
                tok_in_import = get_tok(ctx);
                if(tok_in_import == tok_tab){
                    break;
                }

                if(ctx->identifier_str == "as" || ctx->identifier_str == "from"){
                    import_code_str = import_code_str + " " + ctx->identifier_str + " ";
                }else{
                    import_code_str = import_code_str + ctx->identifier_str;
                }
            }

            // 代码加入
            ctx->import_code_str_arr.push_back(import_code_str);
        }
        
        tok_id = get_tok(ctx);
    }
}

// 仅仅分析代码，并提出报告
std::string build_pre_analysis_report(struct paral_py_context* ctx, std::vector<std::string> seqs, std::string function_name){
    // 输出文件名和运行函数名一样
    scan_all_function(ctx);
    
    // 查看要运行的函数
    if(ctx->fun_table.count(function_name) == 0){
        printf("function is not found\n");
        exit(-1);
    }

    struct pre_process_report MR_report;
    // 调用MR适用性的分析程序
    MR_report = input_paral_pre_analysis(ctx, function_name);

    // 输出一个字符串"hadoop_MR",true
    std::string result_str = "\"hadoop_MR\":";
    
    if(MR_report.can_trans == true){
        result_str = result_str + "true,\n";
        // 另外再输出op操作
        result_str = result_str + "\"reduce_op\":\"" + MR_report.op_str + "\"";
    }else{
        result_str = result_str + "false";
    }

    

    return result_str;
}

